package jmine.tec.hydra;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

import jmine.tec.test.Builder;
import bancosys.tec.persist.Persistable;
import bancosys.tec.persist.dao.BaseDAO;
import bancosys.tec.services.testcase.RefDBTestCase;
import bancosys.tec.utils.db.descriptor.FlatReferenceDatabaseBuilder.ReferenceDatabaseDescriptionType;

/**
 * @author lundberg
 */
public abstract class HydraTestCase extends RefDBTestCase {

    public HydraTestCase() {
        super();
    }

    public HydraTestCase(String name) {
        super(name);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected String getControllerSpringId() {
        return "hydraController";
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected HydraController getController() {
        return (HydraController) super.getController();
    }

    public <Bo extends Persistable, DAO extends BaseDAO<Bo>> DAO getDAOByClass(Class<DAO> daoClass) {
        return this.getController().getDAOFactory().getDAOByClass(daoClass);
    }

    public <B extends Persistable> BaseDAO<B> getGenericDAO(Class<? extends B> type) {
        return this.getController().getDAOFactory().getGenericDAO(type);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected String[] getResourcesBaseReferencia() {
        return new String[]{ "hydra-sample-db.xml" };
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ReferenceDatabaseDescriptionType getReferenceDatabaseDescriptionType() {
        return ReferenceDatabaseDescriptionType.POSTSCRIPT;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected boolean canOptimizeRestartBD() {
        return false;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected String getSpringMainXMLFilename() {
        return "jmine-tec-hydra-test.xml";
    }

    protected <T extends Persistable> Builder<T> persisted(final Builder<T> builder) {
        return new Builder<T>() {

            private T entity;

            @SuppressWarnings("unchecked")
            public T build() {
                if (this.entity == null) {
                    this.entity = builder.build();

                    Type[] genericInterfaces = builder.getClass().getGenericInterfaces();
                    Class<? extends T> persistableType =
                            (Class<? extends T>) ((ParameterizedType) genericInterfaces[0]).getActualTypeArguments()[0];
                    BaseDAO<T> dao = HydraTestCase.this.getGenericDAO(persistableType);

                    dao.save(this.entity);
                }
                return this.entity;
            }
        };
    }
}
